package com.huffman.smart_picture.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrPool;
import com.huffman.smart_picture.domain.constants.RedisConstant;
import com.huffman.smart_picture.domain.entity.FavoritePictureRecord;
import com.huffman.smart_picture.domain.enums.FavoriteTypeEnum;
import com.huffman.smart_picture.mapper.FavoritePictureRecordMapper;
import com.huffman.smart_picture.mapper.PictureMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author DengLin
 * @title 写入用户图片点赞记录任务
 * @date 2025/5/16
 */
@Component
@Slf4j
public class WriteUserFavoritePictureTask {

    @Resource
    private PictureMapper pictureMapper;
    @Resource
    private FavoritePictureRecordMapper favoritePictureRecordMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * 定时任务更新点赞记录到数据库中
     */
    @Scheduled(fixedRate = 10000)
    @Transactional(rollbackFor = Exception.class)
    public void writeRecord() {
        log.info("task:write user favorite picture record to database");
        DateTime nowDate = DateUtil.date();
        // 如果秒数为0~9 则回到上一分钟的50秒
        int second = (DateUtil.second(nowDate) / 10 - 1) * 10;
        if (second == -10) {
            second = 50;
            // 回到上一分钟
            nowDate = DateUtil.offsetMinute(nowDate, -1);
        }
        String timeSlice = DateUtil.format(nowDate, "HH:mm:") + second;
        syncUpdateData(timeSlice);
        log.info("task finish time slice:{}", timeSlice);
    }

    @Scheduled(cron = "0 0 3 * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void CompensatoryRedisData() {
        log.info("task:compensatory user favorite picture record from redis to database");
        String keyPatternPre = String.format(RedisConstant.TEMP_FAVORITE_PICTURE_RECORD_KEY, "");
        Set<String> tempKeys = redisTemplate.keys(keyPatternPre + "*");
        if (CollUtil.isEmpty(tempKeys)) {
            log.info("task finish:no data need compensatory");
            return;
        }
        Set<String> needDeleteKeys = new HashSet<>();
        tempKeys.stream()
                .filter(Objects::nonNull)
                .forEach(key -> needDeleteKeys.add(key.replace(keyPatternPre, "")));
        if (CollUtil.isEmpty(needDeleteKeys)) {
            log.info("task finish:no data need compensatory");
            return;
        }

        // 补偿数据
        for (String needDeleteKey : needDeleteKeys) {
            syncUpdateData(needDeleteKey);
        }
    }

    @Scheduled(cron = "0 0 3 * * ?")
    public void deleteRedisData(){
        String userFavoritePatternPre = String.format(RedisConstant.TEMP_USER_RECORD_KEY, "");
        Set<String> userFavoriteKeys = redisTemplate.keys(userFavoritePatternPre + "*");
        if (CollUtil.isNotEmpty(userFavoriteKeys) && userFavoriteKeys != null) {
            log.info("task:delete user favorite record");
            redisTemplate.delete(userFavoriteKeys);
            log.info("task finish:delete user favorite record");
        }
        log.info("task finish:compensatory user favorite picture record from redis to database");
    }

    public void syncUpdateData(String timeSlice) {
        String tempRecordKey = String.format(RedisConstant.TEMP_FAVORITE_PICTURE_RECORD_KEY, timeSlice);
        // 根据时间获取用户点赞记录Map redis中key为(userId:pictureId)
        Map<Object, Object> tempUserFavoritePictureMap = redisTemplate.opsForHash().entries(tempRecordKey);

        if (CollUtil.isEmpty(tempUserFavoritePictureMap)) {
            return;
        }
        // 图片点赞总数Map(图片id:图片获赞数)
        HashMap<Long, Integer> pictureFavoriteCountMap = new HashMap<>();
        // 需要修改的点赞记录
        List<FavoritePictureRecord> favoritePictureRecords = new ArrayList<>();

        for (Object userIdPictureIdKey : tempUserFavoritePictureMap.keySet()) {
            String userIdAndPictureId = (String) userIdPictureIdKey;
            String[] ids = userIdAndPictureId.split(StrPool.COLON);
            Long userId = Long.valueOf(ids[0]);
            Long pictureId = Long.valueOf(ids[1]);
            Integer favoriteType = (Integer) tempUserFavoritePictureMap.getOrDefault(userIdPictureIdKey, 0);
            // 未改变直接跳过
            if (FavoriteTypeEnum.NONE.getValue().equals(favoriteType)) {
                continue;
            }
            FavoritePictureRecord favoritePictureRecord = new FavoritePictureRecord();
            favoritePictureRecord.setUserId(userId);
            favoritePictureRecord.setPictureId(pictureId);
            favoritePictureRecord.setStatus(favoriteType);
            favoritePictureRecords.add(favoritePictureRecord);
            // 增加点赞
            pictureFavoriteCountMap.put(pictureId, pictureFavoriteCountMap.getOrDefault(pictureId, 0) + favoriteType);
        }

        // 更新/插入点赞记录
        if (CollUtil.isNotEmpty(favoritePictureRecords)) {
            favoritePictureRecordMapper.batchInsertOrUpdate(favoritePictureRecords);
        }

        // 更新点赞记录
        if (CollUtil.isNotEmpty(pictureFavoriteCountMap)) {
            pictureMapper.batchUpdateFavoriteCount(pictureFavoriteCountMap);
        }

        new Thread(() -> {
            if (Boolean.TRUE.equals(redisTemplate.delete(tempRecordKey))) {
                log.info("task:delete {} slice user temp favorite record in redis success", tempRecordKey);
            } else {
                log.error("task:delete {} slice user temp favorite record in redis fail", tempRecordKey);
            }
        }).start();

    }

}
